package codegen.ui.nbvisual;

import org.netbeans.api.visual.action.ActionFactory;
import org.netbeans.api.visual.action.EditProvider;
import org.netbeans.api.visual.vmd.VMDGraphScene;
import org.netbeans.api.visual.vmd.VMDNodeWidget;
import org.netbeans.api.visual.vmd.VMDPinWidget;
import org.netbeans.api.visual.widget.Widget;
import org.openide.util.Utilities;

import java.awt.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import javax.swing.JComponent;
import org.openide.util.ImageUtilities;

/**
 * @author David Kaspar
 */
public class VMDTest {

    private static final Image IMAGE_LIST = ImageUtilities.loadImage("test/resources/list_16.png"); // NOI18N
    private static final Image IMAGE_CANVAS = ImageUtilities.loadImage("test/resources/custom_displayable_16.png"); // NOI18N
    private static final Image IMAGE_COMMAND = ImageUtilities.loadImage("test/resources/command_16.png"); // NOI18N
    private static final Image IMAGE_ITEM = ImageUtilities.loadImage("test/resources/item_16.png"); // NOI18N
    private static final Image GLYPH_PRE_CODE = ImageUtilities.loadImage("test/resources/preCodeGlyph.png"); // NOI18N
    private static final Image GLYPH_POST_CODE = ImageUtilities.loadImage("test/resources/postCodeGlyph.png"); // NOI18N
    private static final Image GLYPH_CANCEL = ImageUtilities.loadImage("test/resources/cancelGlyph.png"); // NOI18N
    private static int nodeID = 1;
    private static int edgeID = 1;
    private VMDGraphScene scene;
    private JComponent view;
    private JComponent SatelliteView;

    public JComponent getView() {
        if (this.view == null) {
            this.view = scene.createView();
        }
        return this.view;
    }

    public JComponent getBirdEyeView() {
        if (this.SatelliteView == null) {
            this.SatelliteView = scene.createSatelliteView();
        }
        return this.SatelliteView;

    }

    public VMDGraphScene createScene() {
        this.scene = new VMDGraphScene();
        String mobile = createNode(scene, 100, 100, IMAGE_LIST, "menu", "List", null);
        createPin(scene, mobile, "start", IMAGE_ITEM, "Start", "Element");
        createPin(scene, mobile, "resume", IMAGE_ITEM, "Resume", "Element");

        String menu = createNode(scene, 400, 400, IMAGE_LIST, "menu", "List", null);
        createPin(scene, menu, "game", IMAGE_ITEM, "New Game", "Element");
        createPin(scene, menu, "options", IMAGE_ITEM, "Options", "Element");
        createPin(scene, menu, "help", IMAGE_ITEM, "Help", "Element");
        createPin(scene, menu, "exit", IMAGE_ITEM, "Exit", "Element");
        createPin(scene, menu, "listCommand1", IMAGE_COMMAND, "Yes", "Command");
        createPin(scene, menu, "listCommand2", IMAGE_COMMAND, "No", "Command");

        String game = createNode(scene, 600, 100, IMAGE_CANVAS, "gameCanvas", "MyCanvas", Arrays.asList(GLYPH_PRE_CODE, GLYPH_CANCEL, GLYPH_POST_CODE));
        createPin(scene, game, "ok", IMAGE_COMMAND, "okCommand1", "Command");
        createPin(scene, game, "cancel", IMAGE_COMMAND, "cancelCommand1", "Command");

        createEdge(scene, "start", menu);
        createEdge2(scene, "resume", "game");

        createEdge(scene, "game", game);
        createEdge(scene, "exit", mobile);

        createEdge(scene, "ok", menu);
        createEdge(scene, "cancel", menu);

        VMDNodeWidget widget = (VMDNodeWidget) scene.findWidget(menu);
        HashMap<String, List<Widget>> categories = new HashMap<String, List<Widget>>();
        categories.put("Elements", Arrays.asList(scene.findWidget("game"), scene.findWidget("options"), scene.findWidget("help"), scene.findWidget("exit")));
        categories.put("Commands", Arrays.asList(scene.findWidget("listCommand1"), scene.findWidget("listCommand2")));
        widget.sortPins(categories);

        scene.getActions().addAction(ActionFactory.createEditAction(new EditProvider() {
            public void edit(Widget widget) {
                scene.layoutScene();
            }
        }));

        return scene;
    }

    static String createNode(VMDGraphScene scene, int x, int y, Image image, String name, String type, List<Image> glyphs) {
        String nodeID = "node" + VMDTest.nodeID++;
        VMDNodeWidget widget = (VMDNodeWidget) scene.addNode(nodeID);
        widget.setPreferredLocation(new Point(x, y));
        widget.setNodeProperties(image, name, type, glyphs);
        scene.addPin(nodeID, nodeID + VMDGraphScene.PIN_ID_DEFAULT_SUFFIX);
        return nodeID;
    }

    static void createPin(VMDGraphScene scene, String nodeID, String pinID, Image image, String name, String type) {
        VMDPinWidget pinWidget = ((VMDPinWidget) scene.addPin(nodeID, pinID));
        pinWidget.setProperties(name, null);


        // uncomment this in case, you would like to allow to move a node by dragging any area of the node (including pins)
//        final Widget nodeWidget = scene.findWidget (nodeID);
//        final WidgetAction originalMoveAction = ActionFactory.createMoveAction ();
//
//        pinWidget.getActions ().addAction (new WidgetAction() {
//
//            public State mouseClicked (Widget widget, WidgetMouseEvent event) {
//                Point point = nodeWidget.convertSceneToLocal (widget.convertLocalToScene (event.getPoint ()));
//                return originalMoveAction.mouseClicked (nodeWidget, new WidgetMouseEvent (event.getEventID (), new MouseEvent (widget.getScene ().getView (), 0, event.getWhen (), event.getModifiersEx (), point.x, point.y, event.getClickCount (), event.isPopupTrigger (), event.getButton ())));
//            }
//
//            public State mousePressed (Widget widget, WidgetMouseEvent event) {
//                Point point = nodeWidget.convertSceneToLocal (widget.convertLocalToScene (event.getPoint ()));
//                return originalMoveAction.mousePressed (nodeWidget, new WidgetMouseEvent (event.getEventID (), new MouseEvent (widget.getScene ().getView (), 0, event.getWhen (), event.getModifiersEx (), point.x, point.y, event.getClickCount (), event.isPopupTrigger (), event.getButton ())));
//            }
//
//            public State mouseReleased (Widget widget, WidgetMouseEvent event) {
//                Point point = nodeWidget.convertSceneToLocal (widget.convertLocalToScene (event.getPoint ()));
//                return originalMoveAction.mouseReleased (nodeWidget, new WidgetMouseEvent (event.getEventID (), new MouseEvent (widget.getScene ().getView (), 0, event.getWhen (), event.getModifiersEx (), point.x, point.y, event.getClickCount (), event.isPopupTrigger (), event.getButton ())));
//            }
//
//            public State mouseEntered (Widget widget, WidgetMouseEvent event) {
//                Point point = nodeWidget.convertSceneToLocal (widget.convertLocalToScene (event.getPoint ()));
//                return originalMoveAction.mouseEntered (nodeWidget, new WidgetMouseEvent (event.getEventID (), new MouseEvent (widget.getScene ().getView (), 0, event.getWhen (), event.getModifiersEx (), point.x, point.y, event.getClickCount (), event.isPopupTrigger (), event.getButton ())));
//            }
//
//            public State mouseExited (Widget widget, WidgetMouseEvent event) {
//                Point point = nodeWidget.convertSceneToLocal (widget.convertLocalToScene (event.getPoint ()));
//                return originalMoveAction.mouseExited (nodeWidget, new WidgetMouseEvent (event.getEventID (), new MouseEvent (widget.getScene ().getView (), 0, event.getWhen (), event.getModifiersEx (), point.x, point.y, event.getClickCount (), event.isPopupTrigger (), event.getButton ())));
//            }
//
//            public State mouseDragged (Widget widget, WidgetMouseEvent event) {
//                Point point = nodeWidget.convertSceneToLocal (widget.convertLocalToScene (event.getPoint ()));
//                return originalMoveAction.mouseDragged (nodeWidget, new WidgetMouseEvent (event.getEventID (), new MouseEvent (widget.getScene ().getView (), 0, event.getWhen (), event.getModifiersEx (), point.x, point.y, event.getClickCount (), event.isPopupTrigger (), event.getButton ())));
//            }
//
//            public State mouseMoved (Widget widget, WidgetMouseEvent event) {
//                Point point = nodeWidget.convertSceneToLocal (widget.convertLocalToScene (event.getPoint ()));
//                return originalMoveAction.mouseMoved (nodeWidget, new WidgetMouseEvent (event.getEventID (), new MouseEvent (widget.getScene ().getView (), 0, event.getWhen (), event.getModifiersEx (), point.x, point.y, event.getClickCount (), event.isPopupTrigger (), event.getButton ())));
//            }
//
//            public State mouseWheelMoved (Widget widget, WidgetMouseWheelEvent event) {
//                Point point = nodeWidget.convertSceneToLocal (widget.convertLocalToScene (event.getPoint ()));
//                return originalMoveAction.mouseWheelMoved (nodeWidget, new WidgetMouseWheelEvent (event.getEventID (), new MouseWheelEvent (widget.getScene ().getView (), 0, event.getWhen (), event.getModifiersEx (), point.x, point.y, event.getClickCount (), event.isPopupTrigger (), event.getScrollType (), event.getScrollAmount (), event.getWheelRotation ())));
//            }
//
//            public State keyTyped (Widget widget, WidgetKeyEvent event) {
//                return originalMoveAction.keyTyped (nodeWidget, event);
//            }
//
//            public State keyPressed (Widget widget, WidgetKeyEvent event) {
//                return originalMoveAction.keyPressed (nodeWidget, event);
//            }
//
//            public State keyReleased (Widget widget, WidgetKeyEvent event) {
//                return originalMoveAction.keyReleased (nodeWidget, event);
//            }
//
//            public State focusGained (Widget widget, WidgetFocusEvent event) {
//                return originalMoveAction.focusGained (nodeWidget, event);
//            }
//
//            public State focusLost (Widget widget, WidgetFocusEvent event) {
//                return originalMoveAction.focusLost (nodeWidget, event);
//            }
//
//            public State dragEnter (Widget widget, WidgetDropTargetDragEvent event) {
//                return originalMoveAction.dragEnter (nodeWidget, event);
//            }
//
//            public State dragOver (Widget widget, WidgetDropTargetDragEvent event) {
//                return originalMoveAction.dragOver (nodeWidget, event);
//            }
//
//            public State dropActionChanged (Widget widget, WidgetDropTargetDragEvent event) {
//                return originalMoveAction.dropActionChanged (nodeWidget, event);
//            }
//
//            public State dragExit (Widget widget, WidgetDropTargetEvent event) {
//                return originalMoveAction.dragExit (nodeWidget, event);
//            }
//
//            public State drop (Widget widget, WidgetDropTargetDropEvent event) {
//                return originalMoveAction.drop (nodeWidget, event);
//            }
//        });
    }

    static void createEdge(VMDGraphScene scene, String sourcePinID, String targetNodeID) {
        String edgeID = "edge" + VMDTest.edgeID++;
        scene.addEdge(edgeID);
        scene.setEdgeSource(edgeID, sourcePinID);
        scene.setEdgeTarget(edgeID, targetNodeID + VMDGraphScene.PIN_ID_DEFAULT_SUFFIX);
    }

    static void createEdge2(VMDGraphScene scene, String sourcePinID, String targetPinID) {
        String edgeID = "edge" + VMDTest.edgeID++;
        scene.addEdge(edgeID);
        scene.setEdgeSource(edgeID, sourcePinID);
        scene.setEdgeTarget(edgeID, targetPinID);
    }
}
